#include "widget.h"
#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QDialog>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QScreen>
#include <QTimer>

#include <KF5/KScreen/kscreen/config.h>
#include <KF5/KScreen/kscreen/configmonitor.h>
#include <KF5/KScreen/kscreen/edid.h>
#include <KF5/KScreen/kscreen/getconfigoperation.h>
#include <KF5/KScreen/kscreen/mode.h>
#include <KF5/KScreen/kscreen/monitor.h>
#include <KF5/KScreen/kscreen/output.h>
#include <KF5/KScreen/kscreen/setconfigoperation.h>
#include <KF5/KScreen/kscreen/types.h>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    connect(qApp, &QGuiApplication::primaryScreenChanged, [=](QScreen *screen) {
        qDebug() << "qt primary Screen changed:" << screen->name() << screen->geometry();
    });

    KScreen::GetConfigOperation *op = new KScreen::GetConfigOperation(KScreen::GetConfigOperation::NoEDID, this);
    connect(op, &KScreen::GetConfigOperation::finished, this, [this](KScreen::ConfigOperation *op) {
        configWatch(op);
    });

    init();
}

Widget::~Widget()
{
}

void Widget::init()
{
    setMinimumWidth(400);
    setMinimumHeight(300);
    setGeometry(0, 0, 400, 300);
    setWindowTitle(tr("libkscreen demo"));

    QHBoxLayout *bottomLayout = new QHBoxLayout;
    bottomLayout->addStretch();
    // bottomLayout->addWidget(quitButton);

    QPushButton *primaryButton = new QPushButton("ChangePrimary", this);
    QObject::connect(primaryButton, &QPushButton::clicked, this, &Widget::slotPrimaryButton);

    QPushButton *monitorButton = new QPushButton("ChangeMonitor", this);
    QObject::connect(monitorButton, &QPushButton::clicked, this, &Widget::slotMonitorButton);

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(primaryButton, 0, 0);
    layout->addWidget(monitorButton, 0, 1);

    QGroupBox *typeGroupBox = new QGroupBox(tr("Control"));
    typeGroupBox->setLayout(layout);

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->addWidget(typeGroupBox);
    mainLayout->addLayout(bottomLayout);
    setLayout(mainLayout);
}

void Widget::configWatch(KScreen::ConfigOperation *op)
{
    m_config = op->config();

    KScreen::ConfigMonitor::instance()->addConfig(m_config);

    connect(m_config.data(), &KScreen::Config::primaryOutputChanged, this, [=](const KScreen::OutputPtr &output) {
        if (!output.isNull()) {
            qDebug() << "primaryOutputChanged:" << output->name() << output->geometry();
        }
    });
    connect(m_config.data(), &KScreen::Config::outputAdded, this, [=](const KScreen::OutputPtr &output) {
        qDebug() << "output added:" << output.data()->name();
    });
    connect(m_config.data(), &KScreen::Config::outputRemoved, this, [=]() {
        qDebug() << "output removed";
    });
    connect(m_config.data(), &KScreen::Config::monitorAdded, this, [=](const KScreen::MonitorPtr &monitor) {
        qDebug() << "monitor added:" << monitor.data()->name();
    });
    connect(m_config.data(), &KScreen::Config::monitorRemoved, this, [=](const QString &monitor) {
        qDebug() << "monitor added:" << monitor;
    });
}

void Widget::slotPrimaryButton()
{
    const KScreen::OutputPtr primary = m_config->primaryOutput();
    KScreen::OutputPtr newPrimary = m_config->primaryOutput();
    const KScreen::OutputList outputs = m_config->outputs();
    for (const KScreen::OutputPtr &output : outputs) {
        if (output->isConnected() && output->isEnabled()) {
            if (output->isPrimary()) {
                qDebug() << "output:" << output->name() << output->geometry();
                continue;
            } else {
                newPrimary = output;
                qWarning() << "[=== checkmode ===]"
                           << "set primary:" << primary->name() << "to" << output->name();
            }
        }
    }

    if (newPrimary != primary) {
        m_config->setPrimaryOutput(newPrimary);
        auto *op = new KScreen::SetConfigOperation(m_config);
        op->exec();
    }
}

void Widget::slotMonitorButton()
{
    KScreen::MonitorList monitors;
    bool currentIsCombine;
    const KScreen::MonitorList oldMonitors = m_config->monitors();
    for (const KScreen::MonitorPtr &monitor : oldMonitors) {
        if (monitor->name() == "virtualbig") {
            currentIsCombine = true;
        }
    }
    if (currentIsCombine) {
        // 还原单屏模式
        const KScreen::OutputList outputs = m_config->outputs();
        for (const KScreen::OutputPtr &output : outputs) {
            if (output->isConnected() && output->isEnabled()) {
                KScreen::MonitorPtr monitor(new KScreen::Monitor);
                KScreen::OutputList ots;
                ots.insert(output->id(), output);
                monitor->setOutputs(ots);
                monitor->setName(output->name());
                monitor->setGeometry(output->geometry());
                monitor->setId(output->name());

                monitors.insert(monitor->name(), monitor);
            }
        }

    } else {
        // 拼接屏模式
        KScreen::MonitorPtr monitor(new KScreen::Monitor);
        KScreen::OutputList outputs = m_config->outputs();
        monitor->setOutputs(outputs);
        monitor->setName("virtualbig");

        KScreen::OutputList ots;
        for (const KScreen::OutputPtr &output : outputs) {
            if (output->isConnected() && output->isEnabled()) {
                if (output->isPrimary()) {
                    continue;
                }
                // 加入拼接，不需要的屏幕不加入即可
                ots.insert(output->id(), output);
            }
        }
        monitor->setOutputs(ots);
        monitors.insert(monitor->name(), monitor);
    }
    m_config->setMonitors(monitors);

    auto *op = new KScreen::SetConfigOperation(m_config);
    op->exec();
}
